package com.exception.global.core.service;

import com.exception.global.core.domain.SubjectSpecification;
import com.exception.global.core.vo.PageVO;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.lang.Nullable;

import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;

/**
 * 基础Service接口
 */
public interface BaseService<T, ID extends Serializable> {

    /**
     * 分页查询
     * @param pageSize 页长
     * @param pageNum 页码
     * @param orderFields 排序字段名称
     * @param direction 排序规则
     * @param fieldNames 查询条件字段名称
     * @param values 查询条件值
     * @return 查询结果
     */
    PageVO<T> findAll(@NotNull Integer pageSize, @NotNull Integer pageNum, String[] orderFields, Sort.Direction direction,
                      String[] fieldNames, Object[] values);

    /**
     * 分页查询
     * @param specification 查询条件
     * @param pageable 分页/排序
     * @return 分页查询结果
     */
    PageVO<T> findAll(@NotNull Specification<T> specification, Pageable pageable);

    /**
     * 根据主键查找唯一对象
     * @param id 主键
     * @return 查询结果对象
     */
    T findById(@NotNull ID id);

    /**
     * 根据字段名称和具体值查找唯一对象
     * @param fieldName 字段名称
     * @param value 具体值
     * @return 查询结果对象
     */
    T findByUnique(@NotNull String fieldName, @NotNull Object value);

    /**
     * 根据字段名称和具体值查找唯一对象
     * @param fieldNames 字段名称
     * @param values 具体值
     * @return 查询结果对象
     */
    T findByUnique(String[] fieldNames, Object[] values);

    /**
     * 根据条件查询对象集合
     * @param fieldNames 查询字段名称
     * @param values 查询值
     * @return 查询对象集合
     */
    List<T> findBy(String[] fieldNames, Object[] values);

    /**
     * 根据条件查询对象集合
     * @param fieldName 查询字段清楚
     * @param value 查询值
     * @return 查询结果
     */
    List<T> findBy(String fieldName, Object value);

    /**
     * 根据条件查询排序后的对象集合
     * @param fieldNames 查询字段名称
     * @param values 查询值
     * @param orderFields 排序字段名称
     * @param direction 排序规则
     * @return 排序后的对象集合
     */
    List<T> findBy(String[] fieldNames, Object[] values, String[] orderFields, Sort.Direction direction);

    /**
     * 根据条件查询排序后的对象集合
     * @param fieldName 查询字段名称
     * @param value 查询值
     * @param orderFields 排序字段名称
     * @param direction 排序规则
     * @return 排序后的对象集合
     */
    List<T> findBy(String fieldName, Object value, String[] orderFields, Sort.Direction direction);

    /**
     * 自定义查询条件进行查询
     * @param spec 查询条件
     * @return 查询结果集合
     */
    List<T> findBy(SubjectSpecification<T> spec);

    /**
     * 自定义查询条件，并对结果进行排序
     * @param spec 查询条件
     * @param sort 排序规则
     * @return 查询结果集合
     */
    List<T> findBy(SubjectSpecification<T> spec, Sort sort);

    /**
     * 保存对象
     * @param t 对象
     * @return 返回保存后的对象
     */
    T save(T t);

    /**
     * 批量保存
     * @param ts 保存对象集合
     * @return 返回保存后的对象集合
     */
    List<T> save(Collection<T> ts);

    /**
     * 根据主键（id）删除对象
     * @param id 主键值
     * @return 返回删除对象
     */
    T deleteById(ID id);

    /**
     * 根据条件删除对象
     * @param fieldNames 字段名称
     * @param values 字段值
     */
    void deleteBy(String[] fieldNames, Object[] values);

}
